package com.heima.comment.service.impl;

import com.heima.comment.context.BaseContext;
import com.heima.comment.dtos.CommentRepayDto;
import com.heima.comment.dtos.CommentRepayLikeDto;
import com.heima.comment.dtos.CommentRepaySaveDto;
import com.heima.comment.pojos.ApComment;
import com.heima.comment.pojos.ApCommentRepay;
import com.heima.comment.pojos.ApCommentRepayLike;
import com.heima.comment.service.ApCommentRepayService;
import com.heima.comment.service.ApCommentService;
import com.heima.comment.vos.CommentVo;
import com.heima.common.constants.CommentConstants;
import com.heima.common.exception.CustomException;
import com.heima.feign.user.UserFeignClient;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.user.dtos.UserDto;
import com.heima.user.pojos.ApUser;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ApCommentRepayServiceImpl implements ApCommentRepayService {

    @Autowired
    private ApCommentService apCommentService;

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 评论回复
     *
     * @param commentRepaySaveDto 前端dto
     */
    @Override
    public void save(CommentRepaySaveDto commentRepaySaveDto) {
        //参数校验
        if (commentRepaySaveDto == null ||
                commentRepaySaveDto.getCommentId() == null ||
                commentRepaySaveDto.getContent() == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        int userId = BaseContext.getCurrentId().intValue();
        //校验是否登录
        if (userId == 0) {
            throw new CustomException(AppHttpCodeEnum.NEED_LOGIN);
        }
        //前端限制评论回复内容不超过140字
        String content = commentRepaySaveDto.getContent();
        String commentId = commentRepaySaveDto.getCommentId();
        //垃圾文本扫描
        apCommentService.apCommentContentScan(content);
        //保存评论回复
        UserDto userDto = new UserDto();
        userDto.setId(userId);
        ResponseResult<ApUser> response = userFeignClient.getUser(userDto);
        if (response.getCode() != AppHttpCodeEnum.SUCCESS.getCode()) {
            throw new CustomException(AppHttpCodeEnum.CALL_INTERFACE_FAIL);
        }
        ApUser apUser = response.getData();
        if (apUser == null) {
            return;
        }
        String authorName = apUser.getName();
        saveApCommentRepayToMongoDb(userId, content, commentId, authorName);
        //评论回复数+1
        ApComment apComment = apCommentService.getApCommentById(commentId);
        Integer reply = apComment.getReply();
        reply += 1;
        apComment.setReply(reply);
        mongoTemplate.save(apComment);

    }

    /**
     * 保存评论回复-MongoDB中
     *
     * @param authorId   作者id
     * @param content    内容
     * @param commentId  评论id
     * @param authorName 作者昵称
     */
    private void saveApCommentRepayToMongoDb(int authorId,
                                             String content,
                                             String commentId,
                                             String authorName) {
        ApCommentRepay apCommentRepay = new ApCommentRepay();
        apCommentRepay.setAuthorId(authorId);
        apCommentRepay.setAuthorName(authorName);
        apCommentRepay.setCommentId(commentId);
        apCommentRepay.setContent(content);
        apCommentRepay.setLikes(0);
        apCommentRepay.setCreatedTime(new Date());
        apCommentRepay.setUpdateTime(new Date());
        mongoTemplate.save(apCommentRepay);
    }

    /**
     * 评论回复列表
     *
     * @param commentRepayDto 前端dto
     * @return 返回结果
     */
    @Override
    public List<CommentVo> load(CommentRepayDto commentRepayDto) {
        //参数校验
        if (commentRepayDto == null ||
                commentRepayDto.getCommentId() == null ||
                commentRepayDto.getMinDate() == null
        ) {
            throw new CustomException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        int userId = BaseContext.getCurrentId().intValue();
        String commentId = commentRepayDto.getCommentId();
        Date minDate = commentRepayDto.getMinDate();
        //查询评论回复列表
        List<ApCommentRepay> apCommentRepays = getApCommentRepays(commentId, minDate);
        //设置前端响应结果
        List<CommentVo> commentVoList = getCommentVo(userId, apCommentRepays);

        return commentVoList;
    }


    /**
     * <h2>前端响应结果</h2>
     * 将当前用户给评论回复点赞内容,高亮显示
     *
     * @param userId          用户id
     * @param apCommentRepays 回复内容
     * @return 返回响应结果
     */
    private List<CommentVo> getCommentVo(int userId, List<ApCommentRepay> apCommentRepays) {
        if (apCommentRepays.size() != 0) {
            List<CommentVo> commentVoList = apCommentRepays.stream().map(apCommentRepay -> {
                CommentVo commentVo = new CommentVo();
                BeanUtils.copyProperties(apCommentRepay, commentVo);
                commentVo.setCreatedTime(apCommentRepay.getCreatedTime().getTime());
                commentVo.setFlag(0);
                //查询当前评论回复是否被当前用户点赞(登录用户和未登录用户)
                if (userId != 0) {
                    //登录用户,查询点赞状态
                    //如果点赞设置0,否则设置为null
                    ApCommentRepayLike apCommentRepayLike = getApCommentRepayLike(userId, apCommentRepay.getId());
                    if (apCommentRepayLike != null) {
                        //已登录,已点赞,设置为0
                        commentVo.setOperation(0);
                    }
                    //已登录用户,未点赞,设置为null,直接使用默认值null
                }
                //未登录用户,未点赞,设置为null,直接使用默认值null
                return commentVo;
            }).collect(Collectors.toList());
            return commentVoList;
        }
        return null;
    }

    /**
     * 查询评论回复列表
     *
     * @param commentId 评论id
     * @param minDate   分页条件-(加载更多:小于最小的查询时间)
     * @return 返回此条评论的所有评论回复
     */
    private List<ApCommentRepay> getApCommentRepays(String commentId, Date minDate) {
        Query commentRepayQuery = Query.query(
                        Criteria.where("commentId").is(commentId)
                                .and("createdTime").lt(minDate)
                )//查询条件
                .with(Sort.by(Sort.Direction.DESC, "createdTime"))//排序条件
                .skip(0)//起始索引:0
                .limit(10);//显示条数:10

        List<ApCommentRepay> apCommentRepays =
                mongoTemplate.find(commentRepayQuery, ApCommentRepay.class);
        return apCommentRepays;
    }

    /**
     * 查询评论回复点赞
     *
     * @param authorId       作者id
     * @param commentRepayId 评论回复id
     * @return 评论回复点赞内容
     */
    private ApCommentRepayLike getApCommentRepayLike(int authorId, String commentRepayId) {
        Query query = Query.query(
                Criteria.where("authorId").is(authorId)
                        .and("commentRepayId").is(commentRepayId)
        );
        ApCommentRepayLike apCommentRepayLike = mongoTemplate.findOne(query, ApCommentRepayLike.class);
        return apCommentRepayLike;
    }


    /**
     * 评论回复点赞
     *
     * @param commentRepayLikeDto 前端dto
     */
    @Override
    public Map<String, Integer> like(CommentRepayLikeDto commentRepayLikeDto) {
        //1参数校验
        if (commentRepayLikeDto == null ||
                commentRepayLikeDto.getCommentRepayId() == null ||
                commentRepayLikeDto.getOperation() == null
        ) {
            throw new CustomException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //2 校验用户是否登录
        int userId = BaseContext.getCurrentId().intValue();
        int likes = 0;//点赞量
        if (userId == 0) {
            throw new CustomException(AppHttpCodeEnum.NEED_LOGIN);
        }
        String commentRepayId = commentRepayLikeDto.getCommentRepayId();//评论回复id
        Short operation = commentRepayLikeDto.getOperation();//点赞行为 0点赞 1取消点赞
        //3 点赞---
        if (operation == CommentConstants.LIKE_OPERATION) {
            likes = commentRepayLike(userId, likes, commentRepayId);
        }
        //3 取消点赞---
        if (operation == CommentConstants.CANCEL_LIKE_OPERATION) {
            likes = commentRepayCancelLike(userId, likes, commentRepayId);
        }

        //封装响应结果
        Map<String, Integer> likesMap = new HashMap<>();
        likesMap.put("likes", likes);
        return likesMap;
    }

    /**
     * 评论回复取消点赞
     *
     * @param authorId       用户id
     * @param likes          点赞量
     * @param commentRepayId 评论回复id
     * @return 返回评论回复取消点赞后的点赞量
     */
    private int commentRepayCancelLike(int authorId, int likes, String commentRepayId) {
        //删除用户评论回复点赞记录
        ApCommentRepayLike apCommentRepayLike = getApCommentRepayLike(authorId, commentRepayId);
        if (apCommentRepayLike != null) {
            removeApCommentRepayLike(authorId, commentRepayId);
        }
        //点赞数量-1
        ApCommentRepay apCommentRepay = getApCommentRepayById(commentRepayId);
        if (apCommentRepay != null) {
            likes = apCommentRepay.getLikes();
            likes = likes <= 0 ? 0 : likes - 1;
            apCommentRepay.setLikes(likes);
            apCommentRepay.setUpdateTime(new Date());
            mongoTemplate.save(apCommentRepay);
        }
        return likes;
    }

    /**
     * 删除用户对此条评论回复的点赞记录
     *
     * @param authorId       用户id
     * @param commentRepayId 评论回复id
     */
    private void removeApCommentRepayLike(int authorId, String commentRepayId) {
        Query query = Query.query(
                Criteria.where("authorId").is(authorId)
                        .and("commentRepayId").is(commentRepayId)
        );
        mongoTemplate.remove(query,ApCommentRepayLike.class);
    }

    /**
     * 评论回复点赞
     *
     * @param authorId       作者id
     * @param likes          点赞量
     * @param commentRepayId 评论回复id
     * @return 返回评论回复点赞后的点赞量
     */
    private int commentRepayLike(int authorId, int likes, String commentRepayId) {
        ApCommentRepayLike apCommentRepayLike = getApCommentRepayLike(authorId, commentRepayId);
        //如果没有,说明第一次点赞,直接保存用户点赞记录
        //点赞量+1==>第一次点赞,插入记录,点赞量+1 第二次以后点赞,点赞量+1
        if (apCommentRepayLike == null) {
            apCommentRepayLike = new ApCommentRepayLike();
            //id字段使用ObjectId自动生成
            apCommentRepayLike.setCommentRepayId(commentRepayId);
            apCommentRepayLike.setAuthorId(authorId);
            mongoTemplate.save(apCommentRepayLike);
        }
        //查询这篇评论的回复记录
        ApCommentRepay apCommentRepay = getApCommentRepayById(commentRepayId);
        //更新点赞数量
        if (apCommentRepay != null) {
            likes = apCommentRepay.getLikes();
            likes += 1;
            apCommentRepay.setLikes(likes);
            apCommentRepay.setUpdateTime(new Date());
            mongoTemplate.save(apCommentRepay);
        }
        return likes;
    }

    /**
     * 查询评论回复
     *
     * @param commentRepayId 评论回复id
     * @return 返回评论回复信息
     */
    private ApCommentRepay getApCommentRepayById(String commentRepayId) {
        Query query = Query.query(
                Criteria.where("_id").is(commentRepayId)
        );
        ApCommentRepay apCommentRepay = mongoTemplate.findOne(query, ApCommentRepay.class);
        return apCommentRepay;
    }
}
